//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#include "DSP.h"

Define_Module(DSP);

DSP::~DSP()
{
    // 定时自消息的取消和删除
    //cancelAndDelete(begin_packet);
}

void DSP::initialize()
{
    trace_index = 0; // 初始化 trace 读取的位置

    // 从 trace.txt 文件中读取内容并且保存至 trace 变量
    std::string filename = "trace.txt";
    trace = readTraceFile(filename);

    // 每个 DSP 节点开始运行
    begin_packet = new cMessage("begin_packet");
    scheduleAt(0, begin_packet);

    // 用于变量监控调试
    WATCH(trace_index);

}

void DSP::handleMessage(cMessage *msg)
{
    // 若收到 self_packet
    if (strcmp(msg->getName(), "begin_packet") == 0)
    {
        // 获取此时 trace 行所对应的 src 和 dst
        std::string src = trace[trace_index][0];
        std::string dst = trace[trace_index][1];

        // 若当前 DSP 与 src 相同, 且允许读取 trace
        // 以 src 为源节点, dst 为目的节点进行发包
        if (getName() == src)
        {
            Packet *packet_tobesent = generateMessage(src.c_str(), dst.c_str());
            send(packet_tobesent, "DSP_inout_gate$o");
            bubble("send message");
        }

        // 取消定时
        cancelAndDelete(begin_packet);
    }
    // 若收到的是普通数据包, 说明此时已经传输至 dst
    else
    {
        bubble("received");
        delete(msg);
    }

    // 将用于表示行数的 trace 自增
    trace_index++;

    if ((trace_index < trace.size()) and (strcmp(getName(), "dsp0") != 0))
    {
        // 持续以定时为 1 秒的间隔, 反复查看
        begin_packet = new cMessage("begin_packet");
        scheduleAt(simTime() + 1, begin_packet);
    }

}

Packet* DSP::generateMessage(const char* src, const char* dst)
{
    // 设置 outer_packet 的名称为 pkname
    char pkname[40];

    // 设置数据包格式，显示源节点和目的节点
    sprintf(pkname, "%s-to-%s", src, dst);

    Packet *outer_packet = new Packet(pkname);

    // 设置源节点和目的节点
    outer_packet->setSrc(src);
    outer_packet->setDst(dst);
    outer_packet->setHopcnt(0);

    return outer_packet;
}

// 读取 trace 文件
std::vector<std::vector<std::string>> DSP::readTraceFile(const std::string& filename) {
    std::vector<std::vector<std::string>> trace;
    std::ifstream file(filename);

    if (!file.is_open()) {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return trace;
    }

    std::string line;
    while (std::getline(file, line)) {
        std::vector<std::string> pair;
        std::stringstream ss(line);
        std::string item;

        // Split the line by '-' and store each part in the vector
        while (std::getline(ss, item, '-')) {
            pair.push_back(item);
        }

        // Push the pair into the trace vector
        trace.push_back(pair);
    }

    file.close();
    return trace;
}


